package br.ufpe.cin.vspeed.gui;
import java.awt.Frame;
import java.awt.GridBagConstraints;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Map;

import javax.swing.BorderFactory;
import javax.swing.GroupLayout;
import javax.swing.JButton;
import javax.swing.JEditorPane;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JProgressBar;
import javax.swing.JRadioButton;
import javax.swing.JScrollPane;
import javax.swing.JSpinner;
import javax.swing.LayoutStyle;
import javax.swing.SpinnerNumberModel;
import javax.swing.WindowConstants;
import javax.swing.border.TitledBorder;

import prefuse.action.filter.GraphDistanceFilter;
import speed2010.middleware.comunicacao.Address;
import speed2010.reformulacao.enums.EnrichmentType;
import speed2010.reformulacao.enums.TemplateType;
import speed2010.reformulacao.query.InstanceResult;
import speed2010.reformulacao.query.QueryResult;
import speed2010.reformulacao.useful.Standards;
import speed2010.reformulacao.useful.Utils;
import speed2010.util.SpeedLocalOntology;
import br.ufpe.cin.vspeed.integration.CommunicationManager;
import br.ufpe.cin.vspeed.query.QueryManager;
import br.ufpe.cin.vspeed.util.SwingUtils;
import br.ufpe.cin.vspeed.view.PrefuseConstants;

public class PanelSparQL extends javax.swing.JPanel {
	private static final long serialVersionUID = 7815236968541974750L;

	private TemplateType template;
	private JScrollPane jScrollPanelQuery;

	private JPanel jPanelDireita;
	private JPanel jPanelEsquerda;
	private JPanel jPanelTemplates;

	private JScrollPane jScrollPaneResults;

	private JProgressBar jProgressBarResults;

	private JRadioButton jRadioButtonNegation;
	private JRadioButton jRadioButtonIntersection;
	private JRadioButton jRadioButtonUnion;
	private JRadioButton jRadioButtonOneConcept;

	private final SpeedLocalOntology sourceOntology;

	private JButton jButtonSubmitQuery;
	private JEditorPane queryText;

	private PanelLegend jPanelLegend;
	private PanelDeepControl jPanelDeepControl;
	private PanelEnrichingVariables jPanelEnrichedVariables;

	private PanelDisplayGraph jPanelGraphDisplay;
	private PanelQueryResults jPanelResults;

	private String dlQuery;

	private final Object mutex = new Object();

	private QueryManager queryManager;

	public PanelSparQL() {
		super();
		initGUI();
		this.sourceOntology = CommunicationManager.getInstance().getSourceOntology();
		this.template = TemplateType.NONE;
	}

	private void initGUI() {
		try {
			final GroupLayout thisLayout = new GroupLayout(this);
			setPreferredSize(new java.awt.Dimension(900, 700));
			setLayout(thisLayout);
			thisLayout.setVerticalGroup(thisLayout
					.createParallelGroup()
					.addComponent(getJPanelEsquerda(), GroupLayout.Alignment.LEADING, 0, 700, Short.MAX_VALUE)
					.addGroup(
							GroupLayout.Alignment.LEADING,
							thisLayout.createSequentialGroup().addGap(11)
									.addComponent(getJPanelDireita(), 0, 684, Short.MAX_VALUE)
									.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)));
			thisLayout.setHorizontalGroup(thisLayout.createSequentialGroup()
					.addComponent(getJPanelEsquerda(), GroupLayout.PREFERRED_SIZE, 418, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
					.addComponent(getJPanelDireita(), 0, 466, Short.MAX_VALUE).addContainerGap());
			this.setSize(900, 700);

		} catch (final Exception e) {
			e.printStackTrace();
		}
	}

	private void submitQuerySParql() {
		if (this.queryText.getText().isEmpty()) {
			SwingUtils.errorMessage(new JFrame(), "Unable to process a empty query.", "Query error!");
			return;
		}

		if (!validateTemplate()) {
			return;
		}

		this.jProgressBarResults.setIndeterminate(true);

		final Thread treadExecuteQuery = new Thread(new Runnable() {
			@Override
			public void run() {
				PanelSparQL.this.jPanelResults.updateRows(new ArrayList<InstanceResult>());
				final List<EnrichmentType> enrichmentVariables = buildEnrichmentVariablesList();
				PanelSparQL.this.queryManager = new QueryManager();
				final String sparqlQuery = PanelSparQL.this.queryText.getText();

				if (sparqlQuery.length() > 0) {
					final Map<Address, QueryResult> queryResults = PanelSparQL.this.queryManager.executeQueryDL(
							PanelSparQL.this.dlQuery, enrichmentVariables);

					if (!queryResults.isEmpty()) {
						final Map<Integer, InstanceResult> results = PanelSparQL.this.queryManager
								.processResults(queryResults);

						if (results.isEmpty()) {
							SwingUtils.infoMessage(new Frame(), "No results found for query: "
									+ PanelSparQL.this.dlQuery, "Query Info.");
						}

						PanelSparQL.this.jPanelResults.setResultsMap(results);

						final List<InstanceResult> instances = PanelSparQL.this.queryManager.buildResultsTree(results);
						PanelSparQL.this.jPanelResults.updateRows(instances);
					} else {
						PanelSparQL.this.jPanelResults.updateRows(new ArrayList<InstanceResult>());
						SwingUtils
								.infoMessage(new Frame(), "No results found for query: " + sparqlQuery, "Query Info.");
					}
				}
				synchronized (PanelSparQL.this.mutex) {
					PanelSparQL.this.mutex.notify();
				}
			}
		});
		treadExecuteQuery.start();

		final Thread threadStopProgressBar = new Thread(new Runnable() {
			@Override
			public void run() {
				synchronized (PanelSparQL.this.mutex) {
					try {
						PanelSparQL.this.mutex.wait();
						PanelSparQL.this.jProgressBarResults.setIndeterminate(false);
					} catch (final InterruptedException e) {
						e.printStackTrace();
					}
				}
			}
		});

		threadStopProgressBar.start();
	}
	private boolean validateTemplate() {
		boolean result = true;

		switch (this.template) {
			case ONE : {
				if (this.queryText.getText().contains("_CONCEPT_")) {
					final String msg = "Please select a concept before submit query.";
					SwingUtils.errorMessage(new JFrame(), msg, "Concept Seelction Error!");
					result = false;
				}
			}
				break;

			case NEGATION : {
				if (this.queryText.getText().contains("_CONCEPT_")) {
					final String msg = "Please select a concept before submit query.";
					SwingUtils.errorMessage(new JFrame(), msg, "Concept Seelction Error!");
					result = false;
				}
			}
				break;

			case UNION : {
				final boolean containsC1 = this.queryText.getText().contains("_CONCEPT1_");
				final boolean containsC2 = this.queryText.getText().contains("_CONCEPT2_");
				if (containsC1 || containsC2) {
					final String msg = "Please select a concept before submit query.";
					SwingUtils.errorMessage(new JFrame(), msg, "Concept Seelction Error!");
					result = false;
				}
			}
				break;

			case INTERSECTION : {
				final boolean containsC1 = this.queryText.getText().contains("_CONCEPT1_");
				final boolean containsC2 = this.queryText.getText().contains("_CONCEPT2_");
				if (containsC1 || containsC2) {
					final String msg = "Please select a concept before submit query.";
					SwingUtils.errorMessage(new JFrame(), msg, "Concept Seelction Error!");
					result = false;
				}
			}
				break;

			default :
				break;
		}

		return result;
	}

	private void oneConceptTemplateBuild() {
		this.queryText.setContentType("text/html");
		this.queryText.setText("");
		this.template = TemplateType.ONE;

		String entityElement = "";
		entityElement = Utils.getHeaderElement("xml:base", this.sourceOntology);
		String preQuery = "";
		preQuery += "<html>SELECT distinct ?x ";
		preQuery += "<br>FROM <" + entityElement + "></br>";
		preQuery += "<br>WHERE { </br>";
		preQuery += "<br>?x rdf:type <" + entityElement + "#<font color=red><b>_CONCEPT_</b></font>>} </br></html>";

		this.queryText.setText(preQuery);
	}

	private void unionTemplateBuild() {
		this.queryText.setContentType("text/html");
		this.queryText.setText("");
		this.template = TemplateType.UNION;

		String entityElement = "";
		entityElement = Utils.getHeaderElement("xml:base", this.sourceOntology);
		String preQuery = "";
		preQuery += "<html>SELECT distinct ?x ";
		preQuery += "<br>FROM <" + entityElement + "></br>";
		preQuery += "<br>WHERE { {</br>";
		preQuery += "<br>?x rdf:type <" + entityElement + "#<font color=red><b>_CONCEPT1_</b></font>> </br>";
		preQuery += "<br>} UNION { </br>";
		preQuery += "<br>?x rdf:type <" + entityElement + "#<font color=red><b>_CONCEPT2_</b></font>> } } </br></html>";

		this.queryText.setText(preQuery);
	}

	private void intersectionTemplateBuild() {
		this.queryText.setContentType("text/html");
		this.queryText.setText("");
		this.template = TemplateType.INTERSECTION;

		String entityElement = "";
		entityElement = Utils.getHeaderElement("xml:base", this.sourceOntology);
		String preQuery = "";
		preQuery += "SELECT distinct ?x ";
		preQuery += "<br>FROM <" + entityElement + "> </br>";
		preQuery += "<br>WHERE { {</br>";
		preQuery += "<br>?x rdf:type <" + entityElement + "#<font color=red><b>_CONCEPT1_</b></font>> </br>";
		preQuery += "<br> . </br>";
		preQuery += "<br>?x rdf:type <" + entityElement + "#<font color=red><b>_CONCEPT2_</b></font>> } }</br>";

		this.queryText.setText(preQuery);
	}

	private void negationTemplateBuild() {
		this.queryText.setContentType("text/html");
		this.queryText.setText("");
		this.template = TemplateType.NEGATION;

		String entityElement = "";
		entityElement = Utils.getHeaderElement("xml:base", this.sourceOntology);

		String preQuery = "";
		preQuery += "<html>SELECT distinct ?x FROM <" + entityElement + "> ";
		preQuery += "<br>WHERE { {</br>";
		preQuery += "<br>?x rdf:type ?y . </br>";
		preQuery += "<br><" + entityElement
				+ "#<font color=red><b>_CONCEPT_</b></font>> rdfs:subClassOf ?y} UNION {</br>";
		preQuery += "<br>?x rdf:type ?z . </br>";
		preQuery += "<br><" + entityElement + "#<font color=red><b>_CONCEPT_</b></font>> </br>";
		preQuery += "<br>rdfs:subClassOf ?y . ?z rdfs:subClassOf ?y . </br>";
		preQuery += "<br>FILTER (?z != <" + entityElement
				+ "#<font color=red><b>_CONCEPT_</b></font>>) }} </br></html>";

		this.queryText.setText(preQuery);
	}

	public void updateQuery(final String conceptName) {
		if (this.queryText.getText().isEmpty()) {
			SwingUtils.errorMessage(new JFrame(), "Please select a query template.", "Concept Selection");
		}

		switch (this.template) {
			case ONE : {
				String query = this.queryText.getText();
				if (query.contains("_CONCEPT_")) {
					query = query.replace("_CONCEPT_", conceptName);
					this.queryText.setText(query);
					this.dlQuery = conceptName;
				} else if (query.contains(this.dlQuery)) {
					query = query.replace(this.dlQuery, conceptName);
					this.queryText.setText(query);
					this.dlQuery = conceptName;
				}
			}
				break;

			case NEGATION : {
				String query = this.queryText.getText();
				if (query.contains("_CONCEPT_")) {
					query = query.replaceAll("_CONCEPT_", conceptName);
					this.queryText.setText(query);
					this.dlQuery = conceptName;
				} else if (query.contains(this.dlQuery)) {
					query = query.replaceAll(this.dlQuery, conceptName);
					this.queryText.setText(query);
					this.dlQuery = conceptName;
				}
			}
				break;

			case UNION : {
				String query = this.queryText.getText();
				final boolean containsC1 = query.contains("_CONCEPT1_");
				final boolean containsC2 = query.contains("_CONCEPT2_");

				if (containsC1 && containsC2) {
					query = query.replace("_CONCEPT1_", conceptName);

					this.queryText.setText(query);
					this.dlQuery = conceptName + " " + Standards.OR_UNICODE;
					SwingUtils.infoMessage(new JFrame(), "Please select another concept", "Concept Selection");
				} else if (!containsC1 && containsC2) {
					query = query.replace("_CONCEPT2_", conceptName);

					this.queryText.setText(query);
					this.dlQuery = this.dlQuery + " " + conceptName;
				}
			}
				break;

			case INTERSECTION : {
				String query = this.queryText.getText();
				final boolean containsC1 = query.contains("_CONCEPT1_");
				final boolean containsC2 = query.contains("_CONCEPT2_");

				if (containsC1 && containsC2) {
					query = query.replace("_CONCEPT1_", conceptName);

					this.queryText.setText(query);
					this.dlQuery = conceptName + " " + Standards.AND_UNICODE;
					SwingUtils.infoMessage(new JFrame(), "Please select another concept", "Concept Selection");
				} else if (!containsC1 && containsC2) {
					query = query.replace("_CONCEPT2_", conceptName);

					this.queryText.setText(query);
					this.dlQuery = this.dlQuery + " " + conceptName;
				}
			}
				break;

			default :
				break;
		}
	}
	private List<EnrichmentType> buildEnrichmentVariablesList() {
		final List<EnrichmentType> enrichmentVariables = new ArrayList<EnrichmentType>();
		final Enumeration<?> elements = this.jPanelEnrichedVariables.getVariablesPriority().elements();

		while (elements.hasMoreElements()) {
			final String element = (String) elements.nextElement();
			for (final EnrichmentType enrichmentType : EnrichmentType.values()) {
				if (enrichmentType.getType().equalsIgnoreCase(element)) {
					enrichmentVariables.add(enrichmentType);
					break;
				}
			}
		}

		return enrichmentVariables;
	}

	private PanelEnrichingVariables getJPanelEnrichingVariables() {
		if (this.jPanelEnrichedVariables == null) {
			this.jPanelEnrichedVariables = new PanelEnrichingVariables();
		}
		return this.jPanelEnrichedVariables;
	}

	private PanelQueryResults getJPanel4() {
		if (this.jPanelResults == null) {
			this.jPanelResults = new PanelQueryResults();
			this.jPanelResults.setPreferredSize(new java.awt.Dimension(415, 126));
		}
		return this.jPanelResults;
	}

	private JButton getJButtonSubmitQuery() {
		if (this.jButtonSubmitQuery == null) {
			this.jButtonSubmitQuery = new JButton();
			this.jButtonSubmitQuery.setText("Submit Query");
			this.jButtonSubmitQuery.addMouseListener(new java.awt.event.MouseAdapter() {
				@Override
				public void mouseClicked(final java.awt.event.MouseEvent e) {
					submitQuerySParql();
				}
			});

		}
		return this.jButtonSubmitQuery;
	}

	private JPanel getJPanelTemplates() {
		if (this.jPanelTemplates == null) {
			this.jPanelTemplates = new JPanel();
			final GroupLayout jPanelTemplatesLayout = new GroupLayout(this.jPanelTemplates);
			this.jPanelTemplates.setLayout(jPanelTemplatesLayout);
			this.jPanelTemplates.setBackground(new java.awt.Color(255, 255, 255));
			this.jPanelTemplates.setBorder(BorderFactory.createTitledBorder(null, "Select the SPARQL Template",
					TitledBorder.LEADING, TitledBorder.DEFAULT_POSITION));
			jPanelTemplatesLayout.setHorizontalGroup(jPanelTemplatesLayout.createSequentialGroup().addContainerGap()
					.addComponent(getJRadioButtonOne(), 0, 109, Short.MAX_VALUE).addGap(21)
					.addComponent(getJRadioButtonUnion(), 0, 93, Short.MAX_VALUE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
					.addComponent(getJRadioButtonIntersection(), 0, 117, Short.MAX_VALUE).addGap(18)
					.addComponent(getJRadioButtonNegation(), 0, 93, Short.MAX_VALUE));
			jPanelTemplatesLayout.setVerticalGroup(jPanelTemplatesLayout
					.createSequentialGroup()
					.addGroup(
							jPanelTemplatesLayout
									.createParallelGroup(GroupLayout.Alignment.BASELINE)
									.addComponent(getJRadioButtonNegation(), GroupLayout.Alignment.BASELINE,
											GroupLayout.PREFERRED_SIZE, 28, GroupLayout.PREFERRED_SIZE)
									.addComponent(getJRadioButtonOne(), GroupLayout.Alignment.BASELINE,
											GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE)
									.addComponent(getJRadioButtonUnion(), GroupLayout.Alignment.BASELINE,
											GroupLayout.PREFERRED_SIZE, 26, GroupLayout.PREFERRED_SIZE)
									.addComponent(getJRadioButtonIntersection(), GroupLayout.Alignment.BASELINE,
											GroupLayout.PREFERRED_SIZE, 25, GroupLayout.PREFERRED_SIZE))
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED));
		}
		return this.jPanelTemplates;
	}

	private JRadioButton getJRadioButtonOne() {
		if (this.jRadioButtonOneConcept == null) {
			this.jRadioButtonOneConcept = new JRadioButton();
			this.jRadioButtonOneConcept.setText("One Concept");
			this.jRadioButtonOneConcept.setBackground(new java.awt.Color(255, 255, 255));
			this.jRadioButtonOneConcept.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(final java.awt.event.ActionEvent e) {
					PanelSparQL.this.jRadioButtonIntersection.setSelected(false);
					PanelSparQL.this.jRadioButtonNegation.setSelected(false);
					PanelSparQL.this.jRadioButtonUnion.setSelected(false);
					oneConceptTemplateBuild();
				}
			});
		}
		return this.jRadioButtonOneConcept;
	}

	private JRadioButton getJRadioButtonUnion() {
		if (this.jRadioButtonUnion == null) {
			this.jRadioButtonUnion = new JRadioButton();
			this.jRadioButtonUnion.setText("Union");
			this.jRadioButtonUnion.setBackground(new java.awt.Color(255, 255, 255));
			this.jRadioButtonUnion.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(final java.awt.event.ActionEvent e) {
					PanelSparQL.this.jRadioButtonOneConcept.setSelected(false);
					PanelSparQL.this.jRadioButtonIntersection.setSelected(false);
					PanelSparQL.this.jRadioButtonNegation.setSelected(false);
					unionTemplateBuild();

				}
			});
		}
		return this.jRadioButtonUnion;
	}

	private JRadioButton getJRadioButtonIntersection() {
		if (this.jRadioButtonIntersection == null) {
			this.jRadioButtonIntersection = new JRadioButton();
			this.jRadioButtonIntersection.setText("Intersection");
			this.jRadioButtonIntersection.setBackground(new java.awt.Color(255, 255, 255));
			this.jRadioButtonIntersection.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(final java.awt.event.ActionEvent e) {
					PanelSparQL.this.jRadioButtonUnion.setSelected(false);
					PanelSparQL.this.jRadioButtonOneConcept.setSelected(false);
					PanelSparQL.this.jRadioButtonNegation.setSelected(false);
					intersectionTemplateBuild();
				}
			});
		}
		return this.jRadioButtonIntersection;
	}

	private JRadioButton getJRadioButtonNegation() {
		if (this.jRadioButtonNegation == null) {
			this.jRadioButtonNegation = new JRadioButton();
			this.jRadioButtonNegation.setText("Negation");
			this.jRadioButtonNegation.setBackground(new java.awt.Color(255, 255, 255));
			this.jRadioButtonNegation.addActionListener(new java.awt.event.ActionListener() {
				@Override
				public void actionPerformed(final java.awt.event.ActionEvent e) {
					PanelSparQL.this.jRadioButtonUnion.setSelected(false);
					PanelSparQL.this.jRadioButtonOneConcept.setSelected(false);
					PanelSparQL.this.jRadioButtonIntersection.setSelected(false);
					negationTemplateBuild();

				}
			});
		}
		return this.jRadioButtonNegation;
	}

	private JProgressBar getJProgressBarResults() {
		if (this.jProgressBarResults == null) {
			this.jProgressBarResults = new JProgressBar();
		}
		return this.jProgressBarResults;
	}

	private JScrollPane getJScrollPaneResults() {
		if (this.jScrollPaneResults == null) {
			this.jScrollPaneResults = new JScrollPane();
			this.jScrollPaneResults.setViewportView(getJPanel4());
		}
		return this.jScrollPaneResults;
	}

	private JEditorPane getJEditorPanelQuery() {
		if (this.queryText == null) {
			this.queryText = new JEditorPane();
			//queryText.setContentType("text/html");
			this.queryText.setEditable(false);
			this.queryText.setPreferredSize(new java.awt.Dimension(421, 204));
			this.queryText.setFont(new java.awt.Font("Monospaced", 0, 11));
			this.queryText.setText("");
		}
		return this.queryText;
	}

	private JPanel getJPanelDireita() {
		if (this.jPanelDireita == null) {
			this.jPanelDireita = new JPanel();
			final GroupLayout jPanel1Layout = new GroupLayout(this.jPanelDireita);
			this.jPanelDireita.setLayout(jPanel1Layout);
			jPanel1Layout.setHorizontalGroup(jPanel1Layout
					.createParallelGroup()
					.addGroup(
							GroupLayout.Alignment.LEADING,
							jPanel1Layout
									.createParallelGroup()
									.addComponent(getJScrollPaneQuery(), GroupLayout.Alignment.LEADING, 0, 466,
											Short.MAX_VALUE)
									.addComponent(getJPanelEnrichingVariables(), GroupLayout.Alignment.LEADING, 0, 466,
											Short.MAX_VALUE)
									.addComponent(getJProgressBarResults(), GroupLayout.Alignment.LEADING, 0, 466,
											Short.MAX_VALUE)
									.addComponent(getJScrollPaneResults(), GroupLayout.Alignment.LEADING, 0, 466,
											Short.MAX_VALUE)
									.addComponent(getJPanelTemplates(), GroupLayout.Alignment.LEADING, 0, 466,
											Short.MAX_VALUE))
					.addGroup(
							GroupLayout.Alignment.LEADING,
							jPanel1Layout
									.createSequentialGroup()
									.addGap(0, 322, Short.MAX_VALUE)
									.addComponent(getJButtonSubmitQuery(), GroupLayout.PREFERRED_SIZE, 144,
											GroupLayout.PREFERRED_SIZE)));
			jPanel1Layout.setVerticalGroup(jPanel1Layout
					.createSequentialGroup()
					.addComponent(getJPanelTemplates(), GroupLayout.PREFERRED_SIZE, 53, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
					.addComponent(getJScrollPaneQuery(), GroupLayout.PREFERRED_SIZE, 218, GroupLayout.PREFERRED_SIZE)
					.addGap(16)
					.addComponent(getJPanelEnrichingVariables(), GroupLayout.PREFERRED_SIZE, 151,
							GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED, 0, GroupLayout.PREFERRED_SIZE)
					.addComponent(getJButtonSubmitQuery(), GroupLayout.PREFERRED_SIZE, 31, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
					.addComponent(getJScrollPaneResults(), GroupLayout.PREFERRED_SIZE, 148, GroupLayout.PREFERRED_SIZE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
					.addComponent(getJProgressBarResults(), GroupLayout.PREFERRED_SIZE, 21, GroupLayout.PREFERRED_SIZE)
					.addContainerGap(GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE));
		}
		return this.jPanelDireita;
	}

	private JPanel getJPanelEsquerda() {
		if (this.jPanelEsquerda == null) {
			this.jPanelGraphDisplay = getJPanelGraphDisplay();
			this.jPanelEsquerda = new JPanel();
			final GroupLayout jPanelEsquerdaLayout = new GroupLayout(this.jPanelEsquerda);
			this.jPanelEsquerda.setLayout(jPanelEsquerdaLayout);
			this.jPanelEsquerda.setBackground(new java.awt.Color(255, 255, 255));
			jPanelEsquerdaLayout.setHorizontalGroup(jPanelEsquerdaLayout
					.createSequentialGroup()
					.addContainerGap()
					.addGroup(
							jPanelEsquerdaLayout
									.createParallelGroup()
									.addGroup(
											GroupLayout.Alignment.LEADING,
											jPanelEsquerdaLayout
													.createSequentialGroup()
													.addComponent(getJPanelLegend(), GroupLayout.PREFERRED_SIZE, 216,
															GroupLayout.PREFERRED_SIZE)
													.addPreferredGap(LayoutStyle.ComponentPlacement.UNRELATED)
													.addComponent(getJPanelDeepControl(), 0, 169, Short.MAX_VALUE)
													.addGap(13))
									.addComponent(this.jPanelGraphDisplay, GroupLayout.Alignment.LEADING, 0, 408,
											Short.MAX_VALUE)));
			jPanelEsquerdaLayout.setVerticalGroup(jPanelEsquerdaLayout
					.createSequentialGroup()
					.addContainerGap()
					.addComponent(this.jPanelGraphDisplay, 0, 555, Short.MAX_VALUE)
					.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED)
					.addGroup(
							jPanelEsquerdaLayout
									.createParallelGroup()
									.addComponent(getJPanelDeepControl(), GroupLayout.Alignment.LEADING, 0, 128,
											Short.MAX_VALUE)
									.addGroup(
											jPanelEsquerdaLayout
													.createSequentialGroup()
													.addComponent(getJPanelLegend(), GroupLayout.PREFERRED_SIZE, 126,
															GroupLayout.PREFERRED_SIZE)
													.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED))));
		}
		return this.jPanelEsquerda;
	}

	private PanelDisplayGraph getJPanelGraphDisplay() {
		if (this.jPanelGraphDisplay == null) {
			if (CommunicationManager.getInstance().isInitialized()) {
				this.jPanelGraphDisplay = new PanelDisplayGraph(this);
			} else {
				this.jPanelGraphDisplay = null;
			}
		}
		return this.jPanelGraphDisplay;
	}

	private PanelLegend getJPanelLegend() {
		if (this.jPanelLegend == null) {
			this.jPanelLegend = new PanelLegend();
			this.jPanelLegend.setText(buildLegend());
		}
		return this.jPanelLegend;
	}

	private PanelDeepControl getJPanelDeepControl() {
		if (this.jPanelDeepControl == null) {
			this.jPanelDeepControl = new PanelDeepControl();
			buildDeepControl();
		}
		return this.jPanelDeepControl;
	}

	private String buildLegend() {
		final String nodeColor = Integer.toHexString(PrefuseConstants.NODE_COLOR_CLASS & 0x00ffffff);
		final String nodeSelected = Integer.toHexString(PrefuseConstants.NODE_COLOR_SELECTED & 0x00ffffff);
		final String nodeHighlighted = Integer.toHexString(PrefuseConstants.NODE_COLOR_HIGHLIGHTED & 0x00ffffff);
		final String nodeSearch = Integer.toHexString(PrefuseConstants.NODE_COLOR_SEARCH & 0x00ffffff);

		final StringBuilder sb = new StringBuilder();
		sb.append("<html><body>");
		sb.append("<table>");
		sb.append("<tr>");
		sb.append("<td bgcolor=\"").append(nodeColor).append("\" width=\"9px\"/>");
		sb.append("<td>OWL Class</td>");
		sb.append("</tr>");
		sb.append("<tr>");
		sb.append("<td bgcolor=\"").append(nodeSelected).append("\"/>");
		sb.append("<td>Selected Node</td>");
		sb.append("</tr>");
		sb.append("<tr>");
		sb.append("<td bgcolor=\"").append(nodeHighlighted).append("\"/>");;
		sb.append("<td>Neighbors of Selected Node</td>");
		sb.append("</tr>");
		sb.append("<tr>");
		sb.append("<td bgcolor=\"").append(nodeSearch).append("\"/>");
		sb.append("<td>Search Result</td>");
		sb.append("</tr>");
		sb.append("</body></html");

		return sb.toString();
	}

	private void buildDeepControl() {
		// Get the GraphDistanceFilter.
		final GraphDistanceFilter filter = this.jPanelGraphDisplay.getOntologyDisplay().getDistanceFilter();

		final GridBagConstraints constraints = new GridBagConstraints();
		constraints.anchor = GridBagConstraints.FIRST_LINE_START;

		// Create the label.
		final JLabel label = new JLabel("Level Numbers: ");

		// Create the spinner and its model.
		final SpinnerNumberModel model = new SpinnerNumberModel(filter.getDistance(), 0, null, 1);
		this.jPanelGraphDisplay.setSpinner(new JSpinner());
		this.jPanelGraphDisplay.getSpinner().addChangeListener(this.jPanelGraphDisplay);
		this.jPanelGraphDisplay.getSpinner().setModel(model);

		// Add the label and the spinner to the panel.
		constraints.gridx = 0;
		constraints.gridy = 0;
		this.jPanelDeepControl.add(label, constraints);
		constraints.gridx = 1;
		constraints.weighty = 1;
		this.jPanelDeepControl.add(this.jPanelGraphDisplay.getSpinner(), constraints);

		// Set the background of the panel.
		this.jPanelDeepControl.setBackground(this.jPanelGraphDisplay.getOntologyDisplay().getBackground());
	}

	/**
	 * User only to preview the form design
	 * 
	 * @param args
	 */
	public static void main(final String[] args) {
		final JFrame frameResultInfo = new JFrame();
		final PanelSparQL panelResultInformation = new PanelSparQL();
		frameResultInfo.getContentPane().add(panelResultInformation);
		frameResultInfo.setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);
		frameResultInfo.pack();
		frameResultInfo.setLocationRelativeTo(frameResultInfo.getRootPane());
		frameResultInfo.setVisible(true);
	}

	private JScrollPane getJScrollPaneQuery() {
		if (this.jScrollPanelQuery == null) {
			this.jScrollPanelQuery = new JScrollPane();
			this.jScrollPanelQuery.setFont(new java.awt.Font("Tahoma", 0, 11));
			this.jScrollPanelQuery.setViewportView(getJEditorPanelQuery());
		}
		return this.jScrollPanelQuery;
	}
}
